// Copyright 2020-2022 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"

#include "esp_http_server.h"
#include "sdkconfig.h"
#include "esp_log.h"

static httpd_handle_t pic_httpd = NULL;

static const char *TAG = "pic_s";

#define CONFIG_IMAGE_JPEG_FORMAT (1)

/* Handler to download a file kept on the server */
static esp_err_t pic_get_handler(httpd_req_t *req)
{
    esp_err_t res = ESP_OK;
    static uint32_t pic_index = 0;
    size_t image_data_buf_len = 0;
    uint8_t *image_data_buf = NULL;
    extern const unsigned char pic1_jpg_start[] asm("_binary_pic1_jpg_start");
    extern const unsigned char pic1_jpg_end[]   asm("_binary_pic1_jpg_end");
    extern const unsigned char pic2_jpg_start[] asm("_binary_pic2_jpg_start");
    extern const unsigned char pic2_jpg_end[]   asm("_binary_pic2_jpg_end");

#if CONFIG_IMAGE_JPEG_FORMAT
    httpd_resp_set_type(req, "image/jpg");
    httpd_resp_set_hdr(req, "Content-Disposition", "inline; filename=capture.jpg");
#elif CONFIG_IMAGE_BMP_FORMAT
    httpd_resp_set_type(req, "image/bmp");
    httpd_resp_set_hdr(req, "Content-Disposition", "inline; filename=capture.bmp");
#endif
    httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");

    switch (pic_index) {
    case 0:
        image_data_buf_len = (pic1_jpg_end - pic1_jpg_start);
        image_data_buf = pic1_jpg_start;
        pic_index = 1;
        break;
    case 1:
        image_data_buf_len = (pic2_jpg_end - pic2_jpg_start);
        image_data_buf = pic2_jpg_start;
        pic_index = 0;
        break;
    default:
        break;
    }

    if (res == ESP_OK) {
        res = httpd_resp_send_chunk(req, (const char *)image_data_buf, image_data_buf_len);
        ESP_LOGI(TAG, "pic len %d", image_data_buf_len);
    } else {
        ESP_LOGW(TAG, "exit pic server");
        return ESP_FAIL;
    }
    /* Respond with an empty chunk to signal HTTP response completion */
    httpd_resp_send_chunk(req, NULL, 0);
    return ESP_OK;
}

/* Handler to redirect incoming GET request for /index.html to /
 * This can be overridden by uploading file with same name */
static esp_err_t index_html_get_handler(httpd_req_t *req)
{
    extern const char html_start[] asm("_binary_index_html_start");
    extern const char html_end[]   asm("_binary_index_html_end");
    const size_t html_size = (html_end - html_start);
    httpd_resp_set_type(req, "text/html");
    /* Add file upload form and script which on execution sends a POST request to /upload */
    httpd_resp_send_chunk(req, (const char*) html_start, html_size);
    /* Respond with an empty chunk to signal HTTP response completion */
    return httpd_resp_send_chunk(req, NULL, 0);
}

/* Handler to respond with an icon file embedded in flash.
 * Browsers expect to GET website icon at URI /favicon.ico.
 * This can be overridden by uploading file with same name */
static esp_err_t favicon_get_handler(httpd_req_t *req)
{
    extern const unsigned char favicon_ico_start[] asm("_binary_favicon_ico_start");
    extern const unsigned char favicon_ico_end[]   asm("_binary_favicon_ico_end");
    const size_t favicon_ico_size = (favicon_ico_end - favicon_ico_start);
    httpd_resp_set_type(req, "image/x-icon");
    httpd_resp_send(req, (const char *)favicon_ico_start, favicon_ico_size);
    return ESP_OK;
}

httpd_uri_t httpd_uri_array[] = {
    {"/", HTTP_GET, index_html_get_handler, NULL},
    {"/favicon.ico", HTTP_GET, favicon_get_handler, NULL},
    {"/pic", HTTP_GET, pic_get_handler, NULL},
};

esp_err_t start_pic_server()
{
    httpd_config_t config = HTTPD_DEFAULT_CONFIG();
    config.stack_size = 5120;

    ESP_LOGI(TAG, "Starting pic server on port: '%d'", config.server_port);
    if (httpd_start(&pic_httpd, &config) == ESP_OK) {
        for (int i = 0; i < sizeof(httpd_uri_array) / sizeof(httpd_uri_t); i++) {
            if (httpd_register_uri_handler(pic_httpd, &httpd_uri_array[i]) != ESP_OK) {
                ESP_LOGE(TAG, "httpd register uri_array[%d] fail", i);
            }
        }
        return ESP_OK;
    }
    return ESP_FAIL;
}